﻿using System;
using System.Collections.Generic;
using System.Linq;
using EtoolTech.MongoDB.Mapper;
using EtoolTech.MongoDB.Mapper.Core;
using EtoolTech.MongoDB.Mapper.Interfaces;
using MongoDB.Driver;

namespace EtoolTech.MondoDB.Utility
{
    public class Config : IConfig
    {
        #region IDatabaseConfig Members

        public string Database
        {
            get { return Program.Database; }
        }

        public string ConnectionString
        {
            get { return "mongodb://" + Program.Server; }
        }

        #endregion
    }

    public class TypeToRebuild
    {
        public string Name { get; set; }
        public List<string> Keys { get; set; }
    }

    public class Program
    {
        public static string Server, Database;


        public static void Main(string[] args)
        {
            Console.Title = "MongoMapper Utility v0.1";

            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine("=> Available Tools:");
            Console.WriteLine("");
            Console.WriteLine("=> 1- Schema Validation Tool");
            Console.WriteLine("=> 2- Add Field Tool");
            Console.WriteLine("=> 3- Rename Field Tool");
            Console.WriteLine("");
            Console.Write("=> Chose your Tool: ");
            string option = Console.ReadLine();

            if (option == "1")
            {
                Console.Clear();
                SchemaValitationTool();
            }
            else
            {
                Console.WriteLine("Not Yet :(");
                Console.ReadLine();
            }
        }

        private static void SchemaValitationTool()
        {
            GetHeaderSchemaValitationTool();

            Console.Write("Server (IP:Port): ");
            Server = Console.ReadLine();
            Console.Clear();

            GetHeaderSchemaValitationTool();

            Console.Write("Database: ");
            Database = Console.ReadLine();
            Console.Clear();

            GetHeaderSchemaValitationTool();

            Console.Write("Assembly: ");
            string assembly = Console.ReadLine();
            Console.Clear();

            //Assembly = @"C:\MongoMapper\EtoolTech.MongoDB.Mapper.Test\bin\Debug\EtoolTech.MongoDB.Mapper.Test.dll";
            //Server = "192.168.1.214:27017";
            //Database = "TestUtility";

            GetHeaderSchemaValitationTool();

            Console.WriteLine("Server:    " + Server);
            Console.WriteLine("Dababase:  " + Database);
            Console.WriteLine("Assenbly:  " + assembly);
            Console.Write("Continue? y/n: ");
            string result = Console.ReadLine();
            Console.WriteLine("");

            if (result.ToUpper() != "Y" && result.ToUpper() != "YES") return;

            System.Reflection.Assembly asm;
            try
            {
                asm = System.Reflection.Assembly.LoadFrom(assembly);
            }
            catch (Exception exc)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Could not load assembly: " + exc.Message);
                Console.ForegroundColor = ConsoleColor.Green;
                return;
            }

            var typesToRebuild = new List<TypeToRebuild>();

            Context.SetDatabaseConfigInterface(new Config());
            Context.ContextGenerated = true;

            IRelations relations = new Relations();

            Console.WriteLine("Reading Assembly Objects:");
            Console.WriteLine("");
            foreach (Type type in asm.GetTypes().Where(c => c.BaseType == typeof (MongoMapper)))
            {
                var indexes = new List<string>();

                Console.WriteLine("=> " + type.FullName);
                Console.WriteLine("");
                Console.WriteLine("Reading PK...");

                string pk = Helper.GetPrimaryKey(type).Aggregate("", (current, field) => current + (field + ","));

                pk = pk.Remove(pk.Length - 1, 1);

                indexes.Add("" + "|" + type.Name + "|" + pk);

                Console.WriteLine("Reading Indexes...");


                string typeName = type.Name;
                indexes.AddRange(Helper.GetIndexes(type).Select(index => "" + "|" + typeName + "|" + index));

                Console.WriteLine("Reading Relations...");

                indexes.AddRange(relations.GetDownRelations(type));
                indexes.AddRange(relations.GetUpRelations(type));

                //Relations.Add(FieldInfo.Name + "|" + RelationAtt.ClassName + "|" + RelationAtt.FieldName);
                foreach (string relation in indexes)
                {
                    string[] tmp = relation.Split('|');

                    var v = from t in typesToRebuild where t.Name == tmp[1] select t;
                    if (v.Count() == 0)
                    {
                        var toRebuild = new TypeToRebuild
                                                      {
                                                          Name = tmp[1],
                                                          Keys = new List<string> {tmp[2]}
                                                      };
                        typesToRebuild.Add(toRebuild);
                    }
                    else
                    {
                        if (!v.First().Keys.Contains(tmp[2]))
                            v.First().Keys.Add(tmp[2]);
                    }
                }

                Console.WriteLine("");
            }

            Console.WriteLine("Validating MongoDB Objects:");
            Console.WriteLine("");

            Console.WriteLine("=> Validating Database: " + Database);
            try
            {

                Helper.Db.GetStats();

            }
            catch (Exception exc)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Could not connect to db: " + exc.Message);
                Console.ForegroundColor = ConsoleColor.Green;
                return;
            }
            Console.WriteLine("Done !!!");
            Console.WriteLine("");

            foreach (TypeToRebuild typeToRebuild in typesToRebuild)
            {
                Console.WriteLine("=> Validating Collection: " + Helper.GetCollectioName(typeToRebuild.Name));
                MongoCollection col = Helper.GetCollection(typeToRebuild.Name);
                Console.WriteLine("Done !!!");
                //Eliminar indices existentes?????

                foreach (string key in typeToRebuild.Keys)
                {
                    Console.WriteLine("=> Validating Index: " + key);
                    col.EnsureIndex(key.Split(','));
                    Console.WriteLine("Done !!!");
                }
                Console.WriteLine("");
            }

            Console.WriteLine("All Task Done !!!");
            Console.ReadLine();
        }

        private static void GetHeaderSchemaValitationTool()
        {
            Console.WriteLine("=> Schema Validation Tool v0.1");
            Console.WriteLine("");
        }
    }
}